Formius.Element_Container = $.inherit(Formius.Element_Abstract, {
	_elements: [],
	options: {
		showChildErrors: false
	},
	__constructor: function(element, parent, settings) {
		this.__base(element, parent);
		this.settings = settings || this.getForm().getSettings();
		var self = this, container, selectors = this.getForm().getSettings().selectors,
			containerSelector = selectors.container || selectors.field;
		this.getElement().find(this.settings.selectors.element).each(function(i, element) {
			if((container = $(element).parents(containerSelector + ':first')).size() > 0) {
				/* Надо найти более красивое и простое решение */
				/*if (!container.hasClass('f-' + $.identify(self.getElement()))) {
					return;
				}*/
				if (self.getElement().get(0) != container.get(0)) {
					return;
				}
			}
			self.addElement(self.createElement(element));
		});
	},

	/**
	 * @param Formius.Element_Abstract element
	 * @param String name
	 * @return Element_Container
	 */
	addElement: function(element, index, name) {
		if (name) {
			element.setName(name);
		}
		index = Formius.Helper.isNumber(index) && index >= 0 && index <= this._elements.length? parseInt(index) || -1: -1;
		if (index >= 0) {
			this._elements.splice(index, 0, element);
		} else {
			index = this._elements.length;
			this._elements.push(element);
		}
		this.trigger(this.__self.EVENT_ADD, [element, index]);
		if (!this.isForm()) {
			this.getParent().__change();
		}
		return this._elements[index];
	},
	/**
	 * @param DOMElement field
	 * @return Formius.Element_Abstract
	 */
	createElement: function(field) {
		var jField = $(field), element;
		for (var i = 0, len = this.settings.mapper.length; i < len; i++) {
			if (jField.is(this.settings.mapper[i].selector)) {
				try {
					element = new Formius[this.settings.mapper[i].namespace](field, this);
					return element;
				} catch (e) {
					throw e;
//					throw new Error("Class «" + this.settings.mapper[i].namespace + "» don't exist or having errors.");
				}
			}
		}
		throw new Error('Unknown field type.');
	},
	/**
	 * @param Boolean includeChildCodes
	 * @return Array
	 */
	getCode: function(includeChildCodes) {
		var codes = [], c, i, j, len;
		codes = codes.concat(this.__base());
		if (includeChildCodes) {
			var elements = this.getElements();
			for (i = 0, len = elements.length; i < len; i++) {
				c = elements[i].getCode();
				for (j in c) {
					if (c[j] !== null) {
						codes.push(c[j]);
					}
				}
			}
		}
		return codes;
	},
	getContainer: function() {
		return this.getElement();
	},
	getContainerSelector: function() {
		var selectors = this.getForm().getSettings().selectors;
		return selectors.container || selectors.field;
	},
	/**
	 * @param String name
	 * @param Boolean askParent
	 * @return Formius.Element_Abstract
	 */
	getElementByName: function(name, askParent /* = true */) {
		askParent = askParent === false? false: true;
		var i, len, element, elements = this.getElements();
		for (i = 0, len = elements.length; i < len; i++) {
			if (elements[i].getName() == name) {
				return elements[i];
			}
		}
		for (i = 0, len = elements.length; i < len; i++) {
			if (elements[i].isContainer()) {
				if ((element = elements[i].getElementByName(name, false))) {
					return element;
				}
			}
		}
		if (askParent && !this.isForm()) {
			return this.getParent().getElementByName(name);
		}
		return null;
	},
	getElements: function() {
		return this._elements || [];
	},
	getErrorTemplate: function() {
		return this.getForm().getSettings().errors.container;
	},
	/**
	 * @param Boolean includeChildMessages
	 * @return Array
	 */
	getMessage: function(includeChildMessages) {
		includeChildMessages = typeof(includeChildMessages) == 'undefined'
			? (this.getOption('showChildErrors') || false)
			: !(includeChildMessages === false);
		var messages = [], msgs, i, j, len, lenJ;
		messages.concat(this.__base());
		if (includeChildMessages) {
			var label, elements = this.getElements();
			for (i = 0, len = elements.length; i < len; i++) {
				label = elements[i].getLabel();
				msgs = elements[i].getMessage();
				for (j = 0, lenJ = msgs.length; j < lenJ; j++) {
					if (msgs[j] !== null && !(typeof(msgs[j]) == 'number' && isNaN(msgs[j]))) {
						messages.push((label? label + ': ': '') + msgs[j]);
					}
				}
			}
		}
		return messages;
	},
	indexOf: function(element) {
		if (!element && !this.isForm()) {
			return this.getParent().indexOf(this);
		}
		return this.getElements().indexOf(element);
	},
	isContainer: function() {
		return true;
	},
	isTemplate: function() {
		var parent = this.getParent();
		if (parent && !parent.isForm()) {
			return parent.isTemplate();
		}
		return false;
	},
	remove: function(element) {
		var index = this.indexOf(element);
		if (index >= 0) {
			this.removeAt(index);
		}
		return this;
	},
	removeAt: function(index) {
		index = Formius.Helper.isNumber(index) && index >= 0 && this._elements[index]? index: -1;
		if (index >= 0) {
			this.trigger(this.__self.EVENT_REMOVE, [this._elements[index], index]);

//			console.log(this._elements[index].getName());
//			console.log(this._elements.length);
			this._elements[index].getElement().remove();
			this._elements[index] = null;
			this._elements.splice(index, 1);
//			console.log(this._elements.length);
		}
		if (!this.isForm()) {
			this.getParent().__change();
		}
		return this;
	},
	/**
	 * @return Mixed
	 */
	render: function() {
		return this;
	},
	/**
	 * @param Mixed data
	 * @return Void
	 */
	setData: function(data) {
		if (!Formius.Helper.isObject(data)) {
			return this;
		}
		var element = null;
		for (var key in data) {
			if ((element = this.getElementByName(key))) {
				element.setData(data[key]);
			}
		}
		return this;
	},

	/**
	 * @param Mixed $data
	 * @return Void
	 */
	setValue: function(values) {
		if (!Formius.Helper.isObject(values)) {
			return this;
		}
		var element = null;
		for (var key in values) {
			if ((element = this.getElementByName(key))) {
				element.setData(values[key]);
			}
		}
		return this;
	},
	showChildErrors: function() {
		return this.getOption('showChildErrors') || false;
	},
	/**
	 * @param Boolean excludeChildMessages
	 * @return Void
	 */
	showMessage: function(excludeChildMessages) {
		var showChildErrors = this.showChildErrors();
		excludeChildMessages = excludeChildMessages || showChildErrors;

		this.__base();
		var i, len, elements = this.getElements();
		if(!excludeChildMessages) {
			for (i = 0, len = elements.length; i < len; i++) {
				elements[i].showMessage();
			}
		} else {
			for (i = 0, len = elements.length; i < len; i++) {
				elements[i].setClasses((elements[i].getMessage().length <= 0));
			}
		}
		return this;
	},

	/**
	 * @return Boolean
	 */
	validate: function() {
		var result = true, elements = this.getElements();
		for (var i = 0, len = elements.length; i < len; i++) {
			result = elements[i].validate() && result;
		}

		result = result && this.__base();

		return result;
	}
}, {
	EVENT_ADD: 'add',
	EVENT_REMOVE: 'remove'
});